package cn.hy.dataSync.config;

import org.apache.commons.lang3.CharUtils;

import java.util.*;

public class CoreConfig extends Properties {
    private static final long serialVersionUID = 8402094826301018982L;

    private CoreConfig() {
        super();
    }

    private CoreConfig(CoreConfig defaults) {
        super(defaults);
    }

    public static CoreConfig create() {
        return new CoreConfig();
    }

    public static CoreConfig create(CoreConfig defaults) {
        return new CoreConfig(defaults);
    }

    public String getString(final String key) {
        Object value = get(key);
        if (null == value) {
            return null;
        }

        return (value instanceof String) ?
                (String) value :
                String.valueOf(value);
    }

    public String getString(final String key, final String defaultValue) {
        String value = this.getString(key);
        if (null == value) {
            return defaultValue;
        }
        return value;
    }

    public Character getChar(final String key) {
        Object value = this.get(key);
        if (null == value) {
            return null;
        }

        try {
            return value instanceof Character ?
                    (Character) value :
                    CharUtils.toChar(String.valueOf(value));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Character getChar(final String key, char defaultValue) {
        Character value = this.getChar(key);
        if (null == value) {
            return defaultValue;
        }
        return value;
    }

    public Boolean getBool(final String key) {
        String result = this.getString(key);
        if (null == result) {
            return null;
        } else if ("true".equalsIgnoreCase(result)) {
            return Boolean.TRUE;
        } else if ("false".equalsIgnoreCase(result)) {
            return Boolean.FALSE;
        }
        return null;
    }

    public Boolean getBool(final String key, boolean defaultValue) {
        Boolean result = this.getBool(key);
        if (null == result) {
            return defaultValue;
        }
        return result;
    }

    public Integer getInteger(final String key) {
        Object value = this.get(key);
        if (null == value) {
            return null;
        }

        try {
            return Integer.valueOf(String.valueOf(value));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Integer getInteger(final String key, int defaultValue) {
        Integer value = this.getInteger(key);
        if (null == value) {
            return defaultValue;
        }
        return value;
    }

    public Long getLong(final String key) {
        Object value = this.get(key);
        if (null == value) {
            return null;
        }

        try {
            return Long.valueOf(String.valueOf(value));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Long getLong(final String key, long defaultValue) {
        Long value = this.getLong(key);
        if (null == value) {
            return defaultValue;
        }
        return value;
    }

    public Double getDouble(final String key) {
        Object value = this.get(key);
        if (null == value) {
            return null;
        }

        try {
            return value instanceof Double ?
                    (Double) value :
                    Double.valueOf(String.valueOf(value));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Double getDouble(final String key, final Double defaultValue) {
        Object value = this.get(key);
        if (null == value) {
            return defaultValue;
        }

        try {
            return value instanceof Double ?
                    (Double) value :
                    Double.valueOf(String.valueOf(value));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("unchecked")
    public List<Object> getList(final String key) {
        Object value = this.get(key);
        if (value instanceof List) {
            return (List<Object>) value;
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> getList(final String key, Class<T> t) {
        List<Object> origin = this.getList(key);
        if (null == origin) {
            return null;
        }

        List<T> result = new ArrayList<>(origin.size());
        for (final Object each : origin) {
            result.add((T) each);
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    public List<Object> getList(final String key,
                                final List<Object> defaultList) {
        List<Object> object = this.getList(key);
        if (null == object) {
            return defaultList;
        }
        return object;
    }

    public <T> List<T> getList(final String key,
                               final List<T> defaultList,
                               Class<T> t) {
        List<T> list = this.getList(key, t);
        if (null == list) {
            return defaultList;
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    public Map<String, Object> getMap(final String key) {
        Object value = this.get(key);
        if (value instanceof Map) {
            return (Map<String, Object>) value;
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public <T> Map<String, T> getMap(final String key, Class<T> t) {
        Map<String, Object> map = this.getMap(key);
        if (null == map) {
            return null;
        }

        Map<String, T> result = new HashMap<>(map.size());
        for (final String k : map.keySet()) {
            result.put(k, (T) map.get(k));
        }
        return result;
    }

    public Map<String, Object> getMap(final String key,
                                      final Map<String, Object> defaultMap) {
        Map<String, Object> object = this.getMap(key);
        if (null == object) {
            return defaultMap;
        }
        return object;
    }

    public <T> Map<String, T> getMap(final String key,
                                     final Map<String, T> defaultMap,
                                     Class<T> t) {
        Map<String, T> result = this.getMap(key, t);
        if (null == result) {
            return defaultMap;
        }
        return result;
    }
}
